import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:whale/helper/utils/util.dart';

import 'model.dart';
import 'widgets/cell.dart';

class AnchorView extends StatefulWidget {
  const AnchorView({
    super.key,
    required this.tabTitles,
    required this.bindItemsBuilder,
    required this.tabBuilder,
    this.physics,
  });

  final Widget Function(int curr, TabController controller) tabBuilder;

  final List<String> tabTitles;
  final IndexedWidgetBuilder bindItemsBuilder;
  final ScrollPhysics? physics;

  @override
  State<AnchorView> createState() => _AnchorViewState();
}

class _AnchorViewState extends State<AnchorView> with TickerProviderStateMixin {
  late final key = GlobalKey();
  double top = 0;
  int curr = 0;
  late TabController tabCtrl;
  late ScrollController sc;
  late List<AnchorModel> list = [];

  void onInit() {
    if (list.length == widget.tabTitles.length) return;

    list = List.generate(widget.tabTitles.length, (i) => AnchorModel(index: i));
    tabCtrl = TabController(length: widget.tabTitles.length, vsync: this)
      ..addListener(onTabChange);

    sc = ScrollController()..addListener(onScrollChange);
  }

  void onTabChange() {
    _getTop();
    final offset = list[tabCtrl.index].off;
    if (offset == null || offset.isNegative) return;
    if (sc.position.userScrollDirection != ScrollDirection.idle) {
      return;
    }
    sc.animateTo(min(offset - top, sc.position.maxScrollExtent),
        duration: const Duration(milliseconds: 300), curve: Curves.bounceInOut);
  }

  void _getTop() {
    if (top > 0) return;
    final box = key.currentContext?.findRenderObject() as RenderBox;
    top = box.localToGlobal(Offset.zero).dy;
  }

  void onScrollChange() {
    _getTop();
    if (sc.position.userScrollDirection == ScrollDirection.idle) {
      return;
    }
    final off = sc.offset + top;

    final index = list.indexWhere((e) {
          if (e.off == null) {
            return false;
          }
          return e.off! > off;
        }) -
        1;
    if (index.isNegative) {
      return;
    }

    if (tabCtrl.index != index) {
      tabCtrl.animateTo(index);
    }
  }

  @override
  void initState() {
    super.initState();
    onInit();
  }

  @override
  void didUpdateWidget(covariant AnchorView oldWidget) {
    onInit();
    super.didUpdateWidget(oldWidget);
  }

  @override
  Widget build(BuildContext context) {
    if (list.isEmpty) {
      return const SizedBox.shrink();
    }
    return Column(
      children: [
        _buildTabbar(),
        _buildList(),
      ],
    );
  }

  Widget _buildTabbar() {
    return widget.tabBuilder(curr, tabCtrl);
  }

  Widget _buildList() {
    return Expanded(
      key: key,
      child: MediaQuery.removePadding(
        context: context,
        removeTop: true,
        removeBottom: true,
        child: ListView.builder(
          controller: sc,
          physics: widget.physics,
          itemBuilder: (context, index) {
            return AnchorCell(
              mod: list[index],
              child: widget.bindItemsBuilder(context, index),
            );
          },
          itemCount: list.length,
        ),
      ),
    );
  }

  @override
  void dispose() {
    tabCtrl.dispose();
    sc.dispose();
    super.dispose();
  }
}
